# Copyright (c) 2024 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import os
import re

def validate_file_header(content):
    pattern = (
        r'^\s*Copyright\s*\(c\)\s*(\d{4})\s*Huawei\s*Technologies\s*Co\.,\s*Ltd\.'
        r'\s*(.*?)\s*is\s*licensed\s*under\s*Mulan\s*PSL\s*v2\.'
        r'\s*You\s*can\s*use\s*this\s*software\s*according\s*to\s*the\s*terms\s*and\s*conditions\s*of\s*the\s*Mulan\s*PSL\s*v2\.'
        r'\s*You\s*may\s*obtain\s*a\s*copy\s*of\s*Mulan\s*PSL\s*v2\s*at:\s*'
        r'http://license\.coscl\.org\.cn/MulanPSL2'
        r'\s*THIS\s*SOFTWARE\s*IS\s*PROVIDED\s*ON\s*AN\s*"AS\s*IS"\s*BASIS,\s*WITHOUT\s*WARRANTIES\s*OF\s*ANY\s*KIND,'
        r'\s*EITHER\s*EXPRESS\s*OR\s*IMPLIED,\s*INCLUDING\s*BUT\s*NOT\s*LIMITED\s*TO\s*NON-INFRINGEMENT,'
        r'\s*MERCHANTABILITY\s*OR\s*FIT\s*FOR\s*A\s*PARTICULAR\s*PURPOSE\.'
        r'(\s*See\s*the\s*Mulan\s*PSL\s*v2\s*for\s*more\s*details\.).*'
    )
    return not re.match(pattern, content, flags=re.DOTALL) is None

def get_suffix(address):
    return address.lower().split('.')[-1]

def get_comment_rules(ext):
    return {
        'py': {
            'single': '#',
            'multi': [
                (r'^(\s*)([\']{3})', r'([\']{3})', None)
            ]
        },
        'sh': {
            'single': '#',
            'multi': []
        },
        'go': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'h': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'cpp': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'c': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'js': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'ts': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'hpp': {
            'single': '//',
            'multi': [
                (r'/\*', r'\*/', r'^\s*\*\s?')
            ]
        },
        'lua': {
            'single': '--',
            'multi': [
                (r'--\[(=*)\[', r'\]\1\]', None)
            ]
        }
    }.get(ext, {})

def no_comment_symbol(code):
    return code.strip('#/*-[]= ')

def get_comments(file_path, ext, rules):
    comments = ''
    with open(file_path, 'r', encoding='utf-8') as file:
        lines = [line.rstrip('\n') for line in file]
    i = 0
    while i < len(lines):
        line = lines[i]
        stripped = line.lstrip()
        multi_matched = False
        # 优先匹配块注释关键字
        for start_pat, end_pat, _ in rules.get('multi', []):
            start_match = re.search(start_pat, line)
            if not start_match:
                continue
            # lua的注释规则很自由，需要做额外的处理
            if ext == 'lua':
                eq_count = len(start_match.group(1))
                end_pat = fr'\]{{={eq_count}+}}\]'
                end_pat = end_pat.replace('+', '') if eq_count > 0 else r'\]{2}'
                end_re = re.compile(end_pat)
            end_re = re.compile(end_pat)
            first_line_content = line[start_match.end():]
            comments += no_comment_symbol(first_line_content)
            if not end_re.search(first_line_content):
                # 如果不是单行的块注释，则将后续的代码视为注释处理，直到出现块注释结束关键字
                i += 1
                while i < len(lines):
                    current_line = lines[i]
                    comments += no_comment_symbol(current_line)
                    if end_re.search(current_line):
                        break
                    else:
                        i += 1
            i += 1
            multi_matched = True
            break
        if multi_matched:
            continue
        # 处理单行注释
        if 'single' in rules and stripped.startswith(rules['single']):
            comments += no_comment_symbol(line)
            i += 1
            continue
        # 遇到非注释内容则终止
        break
    return comments

def checker(dir):
    res = True
    exclude = {'/root/repo/ci-scripts', '/root/repo/ci-repos', '/root/repo/ci-docs'}
    for home, dirs, files in os.walk(dir):
        dirs[:] = [d for d in dirs if not os.path.join(home, d) in exclude]
        for filename in files:
            address = os.path.join(home, filename)
            ext = address.split('.')[-1]
            rules = get_comment_rules(ext)
            if not rules:
                continue
            codes = get_comments(address, ext, rules)
            index = codes.find('Copyright')
            if not validate_file_header(codes[index:]):
                print(address, "的文件头注释不是版权声明或版权声明有误")
                res = False
    return res

if __name__ == "__main__":
    dir = os.getcwd()
    if checker(dir):
        print("文件头注释检测通过")
        exit(0)
    else:
        example = """Copyright (c) (year) Huawei Technologies Co., Ltd.
 openUBMC is licensed under Mulan PSL v2.
 You can use this software according to the terms and conditions of the Mulan PSL v2.
 You may obtain a copy of Mulan PSL v2 at:
         http://license.coscl.org.cn/MulanPSL2
 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 See the Mulan PSL v2 for more details."""
        print("请根据以下模板修改您的文件头注释：\n", example)
        exit(1)